package edu.example;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Collection;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.Vector;

import javax.swing.JOptionPane;

//FOR LOCAL TEST ONLY!!!!!
public class ApplicationManager 
{
	private static ApplicationManager instance = null;
	
	private static UploadAppDialog mainGUI;
	
	private static File ayDataFile;
	private static File ayMapFile;
	
	private static File otsDataFile;
	private static File otsMapFile;
	
	private boolean mapCheckFlag = false;
	
	//Useful data Headers
	private Vector<String> ayHeader =  new Vector<String>();
	
	//Useful data Headers
	private Vector<String> otsHeader =  new Vector<String>();
	
	//AY file Headers
	private Vector<String> ayDataHeader =  new Vector<String>();
	
	//OTS file Headers
	private Vector<String> otsDataHeader =  new Vector<String>();
	
	private Vector<String> dbAyDataHeader = new Vector<String>();
	
	private Vector<String> dbOTSDataHeader = new Vector<String>();
	
	//Newly uploaded Applications
	private TreeMap<String, Application> applications = new TreeMap<String, Application>();
	
	//Applications that already exist in DB
	private TreeMap<String, Application> dbApplications = new TreeMap<String, Application>();
	
	//All applications including newly uploaded and in the DB
	private TreeMap<String, Application> allApplications = new TreeMap<String, Application>();
	
	//Newly uploaded OTS
	private TreeMap<String, OfficialTestScore> OTS = new TreeMap<String , OfficialTestScore>();
	
	//OTSs that already exist in DB
	private TreeMap<String, OfficialTestScore> dbOTS = new TreeMap<String, OfficialTestScore>();
	
	//All OTSs including newly uploaded and in the DB
	private TreeMap<String, OfficialTestScore> allOTS = new TreeMap<String, OfficialTestScore>();
	
	//For toString() only
	private Vector<Vector<String>> ayEntires = new Vector<Vector<String>>();
	
	//For toString() only
	private Vector<Vector<String>> otsEntires = new Vector<Vector<String>>();
	
	
	
	public Vector<String> 						getAYHeader()		{return ayDataHeader;}
	public boolean 								getFlag()			{return mapCheckFlag;}
	public TreeMap<String, Application> 		getAllApps()		{return allApplications;}
	public TreeMap<String, Application> 		getNewApps()		{return applications;}
	public TreeMap<String, OfficialTestScore>	getAllScore()		{return allOTS;}
	
	public static ApplicationManager 			getAppManager()
	{
		 if (instance == null) 
			 instance = new ApplicationManager(mainGUI, ayDataFile,ayMapFile,otsDataFile,otsMapFile);
		 return instance;
	 }
	

	
	public ApplicationManager(UploadAppDialog intiGUI, 
								File initAYDataFile, 
								File initAYMapFile,
								File initOTSFile,
								File initOTSMapFile)
	{
		mainGUI = intiGUI;
		ayDataFile = initAYDataFile;
		ayMapFile = initAYMapFile;
		otsDataFile = initOTSFile;
		otsMapFile = initOTSMapFile;
		if(dbApplications.isEmpty())
		{
			ayDummyDatabaseRead();
		}
		if(dbOTS.isEmpty())
		{
			OTSDummyDatabaseRead();
		}
		if(ayDataFile != null)
		{
			ayDataProcessing(ayDataFile,ayMapFile);
		}
		if(otsDataFile != null)
		{
			otsDataProcessing(otsDataFile,otsMapFile);
		}
	}
	
	
	//For TEST ONLY!!!
	public void ayDummyDatabaseRead()
	{
		File dataFile = new File("AY.txt");
		File mapFile = new File("AY-map.txt");;
		
		int size = 0;
		int lineCounter = 0;
		String word[] = null;
		try
		{
			FileInputStream fis = new FileInputStream(dataFile);
			DataInputStream din = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(din));
			String strLine;
			while ((strLine = br.readLine()) != null)   
			{
				TreeMap<String, String> CurrentData = new TreeMap<String, String>();
				Vector<String> CurrentDataEntry = new Vector<String>();
				
				CurrentDataEntry.setSize(size);
				
				//Get rid of ""
				strLine = strLine.replaceAll("\"", "");
				
				for(int i = 0; i < strLine.length(); i++)
				{
					word = strLine.split("	");
				}
				if (lineCounter == 0)
				{
					for(int i = 0; i < word.length; i++)
					{
						dbAyDataHeader.add(i, word[i]);
						size = dbAyDataHeader.size();
					}
					mappingCheck(dbAyDataHeader, mapFile, "AY");
				}
				else
				{
					for(int i = 0; i < word.length; i++)
						CurrentDataEntry.add(i, word[i]);
					//ayEntires.add(CurrentDataEntry);
					for(int i = 0; i < dbAyDataHeader.size(); i++)
					{
						CurrentData.put(dbAyDataHeader.get(i), CurrentDataEntry.get(i));
						//System.out.println(ayDataHeader.get(i)+": "+CurrentDataEntry.get(i));
					}
					Application newApp = new Application(CurrentData);
					newApp.setNumDesiredReviews(3);
					dbApplications.put(newApp.getEmailAddress(), newApp);
					allApplications.put(newApp.getEmailAddress(), newApp);
					
					/*
					conn.setAutoCommit(false);
    			            PreparedStatement stmt = conn.prepareStatement("INSERT INTO aydata VALUES (?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?)");
    			            for(int i = 0; i < ayDataHeader.size(); i++){
    			            stmt.setString(i+1,  CurrentDataEntry.get(i));
    			            }
    			            stmt.addBatch();
    			            
    			            // submit the batch for execution
    			            int[] updateCounts = stmt.executeBatch();
    			            conn.commit(); */
				}
				lineCounter++;
			}
			din.close();
			/*
			conn.close();
			 */
		}
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}		 
	}
	
	//For TEST ONLY!!!
	public void OTSDummyDatabaseRead()
	{
		File dataFile = new File("OTS.txt");
		File mapFile = new File("OTS-map.txt");;
		
		int size = 0;
		int lineCounter = 0;
		String word[] = null;
		try
		{
			FileInputStream fis = new FileInputStream(dataFile);
			DataInputStream din = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(din));
			String strLine;
			while ((strLine = br.readLine()) != null)   
			{
				TreeMap<String, String> CurrentData = new TreeMap<String, String>();
				Vector<String> CurrentDataEntry = new Vector<String>();
				
				CurrentDataEntry.setSize(size);
				
				//Get rid of ""
				strLine = strLine.replaceAll("\"", "");
				
				for(int i = 0; i < strLine.length(); i++)
				{
					word = strLine.split("	");
				}
				if (lineCounter == 0)
				{
					for(int i = 0; i < word.length; i++)
					{
						dbOTSDataHeader.add(i, word[i]);
						size = dbOTSDataHeader.size();
					}
					mappingCheck(dbOTSDataHeader, mapFile, "OTS");
				}
				else
				{
					for(int i = 0; i < word.length; i++)
						CurrentDataEntry.add(i, word[i]);
					//ayEntires.add(CurrentDataEntry);
					for(int i = 0; i < dbOTSDataHeader.size(); i++)
					{
						CurrentData.put(dbOTSDataHeader.get(i), CurrentDataEntry.get(i));
						//System.out.println(ayDataHeader.get(i)+": "+CurrentDataEntry.get(i));
					}
					OfficialTestScore newScore = new OfficialTestScore(CurrentData);
					dbOTS.put(newScore.getEmailAddress(), newScore);
					allOTS.put(newScore.getEmailAddress(), newScore);
					/*
					conn.setAutoCommit(false);
    			            PreparedStatement stmt = conn.prepareStatement("INSERT INTO aydata VALUES (?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?)");
    			            for(int i = 0; i < ayDataHeader.size(); i++){
    			            stmt.setString(i+1,  CurrentDataEntry.get(i));
    			            }
    			            stmt.addBatch();
    			            
    			            // submit the batch for execution
    			            int[] updateCounts = stmt.executeBatch();
    			            conn.commit(); */
				}
				lineCounter++;
			}
			din.close();
			/*
			conn.close();
			 */
		}
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}		 
	}
	
	public void ayDataProcessing(File dataFile, File mapFile)
	{
		int size = 0;
		int lineCounter = 0;
		String word[] = null;
		try
		{
			FileInputStream fis = new FileInputStream(dataFile);
			DataInputStream din = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(din));
			String strLine;
			while ((strLine = br.readLine()) != null)   
			{
				TreeMap<String, String> CurrentData = new TreeMap<String, String>();
				Vector<String> CurrentDataEntry = new Vector<String>();
				
				CurrentDataEntry.setSize(size);
				
				//Get rid of ""
				strLine = strLine.replaceAll("\"", "");
				
				for(int i = 0; i < strLine.length(); i++)
				{
					word = strLine.split("	");
				}
				if (lineCounter == 0)
				{
					for(int i = 0; i < word.length; i++)
					{
						ayDataHeader.add(i, word[i]);
						size = ayDataHeader.size();
					}
					mappingCheck(ayDataHeader, mapFile, "AY");
				}
				else
				{
					for(int i = 0; i < word.length; i++)
						CurrentDataEntry.add(i, word[i]);
					ayEntires.add(CurrentDataEntry);
					for(int i = 0; i < ayDataHeader.size(); i++)
					{
						CurrentData.put(ayDataHeader.get(i), CurrentDataEntry.get(i));
						//System.out.println(ayDataHeader.get(i)+": "+CurrentDataEntry.get(i));
					}
					Application newApp = new Application(CurrentData);
					newApp.setNumDesiredReviews(3);
					
					
					if(allApplications.containsKey(newApp.getEmailAddress()))
					{
						allApplications.put(newApp.getEmailAddress(), newApp);
					}
					else
					{
						applications.put(newApp.getEmailAddress(), newApp);
						allApplications.put(newApp.getEmailAddress(), newApp);
					}
					
					/*conn.setAutoCommit(false);
    			            PreparedStatement stmt = conn.prepareStatement("INSERT INTO aydata VALUES (?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, " +
    			            		"?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?,?, ?,?,?,?)");
    			            for(int i = 0; i < ayDataHeader.size(); i++){
    			            stmt.setString(i+1,  CurrentDataEntry.get(i));
    			            }
    			            stmt.addBatch();
    			            
    			            // submit the batch for execution
    			            int[] updateCounts = stmt.executeBatch();
    			            conn.commit(); */
				}
				lineCounter++;
			}
			din.close();
			/*
			conn.close();
			 */
		}
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}		 
	}
	
	public void otsDataProcessing(File dataFile, File mapFile)
	{
		int size = 0;
		int lineCounter = 0;
		String word[] = null;
		try
		{
			FileInputStream fis = new FileInputStream(dataFile);
			DataInputStream din = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(din));
			String strLine;
			while ((strLine = br.readLine()) != null)   
			{
				TreeMap<String, String> CurrentData = new TreeMap<String, String>();
				Vector<String> CurrentDataEntry = new Vector<String>();
				
				CurrentDataEntry.setSize(size);
				
				//Get rid of ""
				strLine = strLine.replaceAll("\"", "");
				
				for(int i = 0; i < strLine.length(); i++)
				{
					word = strLine.split("	");
				}
				if(lineCounter == 0)
				{
					for(int i = 0; i < word.length; i++)
					{
						otsDataHeader.add(i, word[i].trim());
						size = otsDataHeader.size();
					}
					mappingCheck(otsDataHeader, mapFile,"OTS");
				}
				else
				{
					for(int i = 0; i < word.length; i++)
						CurrentDataEntry.add(i, word[i].trim());
					otsEntires.add(CurrentDataEntry);
					for(int i = 0; i < otsDataHeader.size(); i++)
					{
						CurrentData.put(otsDataHeader.get(i), CurrentDataEntry.get(i));
					}
					OfficialTestScore newScore = new OfficialTestScore(CurrentData);
					
					if(allOTS.containsKey(newScore.getEmailAddress()))
					{
						allOTS.put(newScore.getEmailAddress(), newScore);
					}
					else
					{
						OTS.put(newScore.getEmailAddress(), newScore);
						allOTS.put(newScore.getEmailAddress(), newScore);
					}
				}

				lineCounter++;
			}
			din.close();
		}		
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}
	}
	
	public boolean mappingCheck(Vector<String> dataHeader, File mappingFile, String dataType)
	{
		int counter = 0;
		String dt = dataType;
		try
		{
			FileInputStream fis = new FileInputStream(mappingFile);
			DataInputStream din = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(din));
			String strLine;
			while ((strLine = br.readLine()) != null)   
			{
				int endIndex = strLine.indexOf("->");
				if(endIndex > 0)
				{
					String mapTo = strLine.substring(endIndex+2);
					String mapHeader = strLine.substring(0, endIndex);
					//System.out.println(mapHeader+" "+mapTo);
					if(mapHeader.equals(dataHeader.get(counter)))
					{
						if(!mapTo.contains("ignore"))
						{
							if(dt.equals("AY"))
							{
								dataHeader.set(counter, mapTo);
							}
							else if(dt.equals("OTS"))
							{
								dataHeader.set(counter, mapTo);
							}
						}
					}
					else
					{
						JOptionPane.showMessageDialog(mainGUI, "Error at line "+(counter+1)+" in "+dataType+" file.", "Mapping error",JOptionPane.ERROR_MESSAGE);
						return mapCheckFlag = false;
					}
				}
				counter++;
			}
			din.close();
		}
		catch (Exception e)
		{
			JOptionPane.showMessageDialog(mainGUI, dataType+" data and "+dataType+" Mapping file doesn't match", "Mapping error",JOptionPane.ERROR_MESSAGE);
			System.err.println("Error: " + e.getMessage());
			return mapCheckFlag = false;
		}		
		
		return mapCheckFlag = true;
	}
	
	public String toString()
	{
		String s = "";
		Collection<Application> temp = allApplications.values();
		Iterator<Application> it = temp.iterator();
			
		while(it.hasNext())
		{
			Application tempApp = it.next();
			Collection<String> tempV = tempApp.getData().values();
			Collection<String> tempK = tempApp.getData().keySet();
			Iterator<String> itK = tempK.iterator();
			Iterator<String> itV = tempV.iterator();
				
			while(itK.hasNext())
			{
				String tempKey = itK.next();
				String tempValue = itV.next();
				
				//Here is the key and value, WRITE IT BACK TO DATABASE
				System.out.println(tempKey+": "+tempValue);
			}
			System.out.println(" ");
		}
		
		
		Collection<OfficialTestScore> tempS = allOTS.values();
		Iterator<OfficialTestScore> itS = tempS.iterator();
			
		while(itS.hasNext())
		{
			OfficialTestScore tempScore = itS.next();
			Collection<String> tempV = tempScore.getData().values();
			Collection<String> tempK = tempScore.getData().keySet();
			Iterator<String> itK = tempK.iterator();
			Iterator<String> itV = tempV.iterator();
			
			while(itK.hasNext())
			{
				String tempKey = itK.next();
				String tempValue = itV.next();
				
				//Here is the key and value, WRITE IT BACK TO DATABASE
				System.out.println(tempKey+": "+tempValue);
			}
			System.out.println(" ");
		}
		return s;
	}
	
	public static void main(String[] args)
	{
		File file1 = new File("AY(New).txt");
		File file2 = new File("AY-map.txt");
		File file3 = new File("OTS.txt");
		File file4 = new File("OTS-map.txt");
		ApplicationManager formatter = new ApplicationManager(null, file1, file2, null, file4);
		System.out.println(formatter.toString());
		//System.out.println(formatter.getApps().get("maurice.wilkes@bmail.com").getApplicantLastName());
	}
}